/*********************
* Author:Dzlua
* QQ:505544956
* time:2016/07/11
*/
#ifndef __EDUI_MSG_H__
#define __EDUI_MSG_H__

#include "Keycode.h"

EDUI_NAMESPACE_BEGIN

class IWindow;

#define EDUI_TEXTMSG_TEXT_SIZE (32)

typedef enum MsgType
{
    MSG_NULL = 0x0,
    MSG_QUIT = 0x100,
    // window msg
    MSG_WND_SHOW = 0x200,
    MSG_WND_HIDDEN,
    MSG_WND_EXPOSED,
    MSG_WND_MOVED,
    MSG_WND_RESIZED,
    MSG_WND_SIZE_CHANGED,
    MSG_WND_MINIMIZED,
    MSG_WND_MAXIMIZED,
    MSG_WND_RESTORED,
    MSG_WND_ENTER,
    MSG_WND_LEAVE,
    MSG_WND_FOCUS_GAINED,
    MSG_WND_FOCUS_LOST,
    MSG_WND_CLOSE,
    //keyboard Msg
    MSG_KEY_DOWN = 0x300,
    MSG_KEY_UP,
    MSG_TEXT_EDITING,
    MSG_TEXT_INPUT,
    //mouse Msg
    MSG_MOUSE_MOVE = 0x400,
    MSG_MOUSE_BUTTON_DOWN,
    MSG_MOUSE_BUTTON_UP,
    MSG_MOUSE_WHEEL,
    /* Drag and drop events */
    MSG_DROPFILE        = 0x1000, /**< The system requests a file open */
    MSG_DROPTEXT,                 /**< text/plain drag-and-drop event */
    MSG_DROPBEGIN,                /**< A new set of drops is beginning (NULL filename) */
    MSG_DROPCOMPLETE,             /**< Current set of drops is now complete (NULL filename) */
    //user Msg
    MSG_USERMSG = 0x8000,
} MsgType;

// common Msg
typedef struct CommonMsg
{
    MsgType msg;
    IWindow* wnd;
} CommonMsg;

// window Msg
typedef struct WndMsg
{
    MsgType msg;
    IWindow* wnd;
    Sint32 data1;       /**< Msg dependent data */
    Sint32 data2;       /**< Msg dependent data */
} WndMsg;

// keyboard Msg
typedef struct KeyboardMsg
{
    MsgType msg;
    IWindow* wnd;
    Uint8 state;        /**< ::EDUI_PRESSED or ::EDUI_RELEASED */
    Uint8 repeat;       /**< Non-zero if this is a key repeat */
    Uint16 mod;         /**< current key modifiers */
    Sint32 key;         /**< key */
    Scancode scan;      /**< physical key code */
} KeyMsg;

// text Msg
typedef struct TextMsg
{
    MsgType msg;
    IWindow* wnd;
    char text[EDUI_TEXTMSG_TEXT_SIZE];    /**< The input/editing text */
    Sint32 start;                         /**< The start cursor of selected editing text */
    Sint32 length;                        /**< The length of selected editing text */
} TextMsg;

#define MOUSE_BUTTON(X)       (1 << ((X)-1))
#define MOUSE_BUTTON_LEFT     1
#define MOUSE_BUTTON_MIDDLE   2
#define MOUSE_BUTTON_RIGHT    3
#define MOUSE_BUTTON_X1       4
#define MOUSE_BUTTON_X2       5
#define MOUSE_BUTTON_LMASK    MOUSE_BUTTON(MOUSE_BUTTON_LEFT)
#define MOUSE_BUTTON_MMASK    MOUSE_BUTTON(MOUSE_BUTTON_MIDDLE)
#define MOUSE_BUTTON_RMASK    MOUSE_BUTTON(MOUSE_BUTTON_RIGHT)
#define MOUSE_BUTTON_X1MASK   MOUSE_BUTTON(MOUSE_BUTTON_X1)
#define MOUSE_BUTTON_X2MASK   MOUSE_BUTTON(MOUSE_BUTTON_X2)

// mouse move Msg
typedef struct MouseMoveMsg
{
    MsgType msg;
    IWindow* wnd;
    Uint32 which;    /**< The mouse instance id */
    Sint32 x;        /**< X coordinate, relative to window */
    Sint32 y;        /**< Y coordinate, relative to window */
    Uint8  state;    /**< The current button state. 1+2+3+4 */
    Sint32 xrel;     /**< The relative motion in the X direction */
    Sint32 yrel;     /**< The relative motion in the Y direction */
} MouseMsg;

// mouse button Msg
typedef struct MouseButtonMsg
{
    MsgType msg;
    IWindow* wnd;
    Uint32 which;       /**< The mouse instance id */
    Sint32 x;           /**< X coordinate, relative to window */
    Sint32 y;           /**< Y coordinate, relative to window */
    Uint8 button;       /**< The mouse button index */
    Uint8 state;        /**< ::EDUI_PRESSED or ::EDUI_RELEASED */
    Uint8 clicks;       /**< 1 for single-click, 2 for double-click, etc. */
} MouseButtonMsg;

// Mouse Wheel Direction
typedef enum
{
    MOUSEWHEEL_NORMAL,    /**< The scroll direction is normal */
    MOUSEWHEEL_FLIPPED    /**< The scroll direction is flipped / natural */
} MouseWheelDirection;

// mouse wheel MsgType
typedef struct MouseWheelMsg
{
    MsgType msg;
    IWindow* wnd;
    Uint32 which;       /**< The mouse instance id */
    Sint32 x;           /**< The amount scrolled horizontally, positive to the right and negative to the left */
    Sint32 y;           /**< The amount scrolled vertically, positive away from the user and negative toward the user */
    MouseWheelDirection direction;   /**< When FLIPPED the values in X and Y will be opposite. Multiply by -1 to change them back */
} MouseWheelMsg;

// drop file Msg
typedef struct DropFileMsg
{
    MsgType msg;
    IWindow* wnd;
    char file[EDUI_MAX_PATH];
} DropFileMsg;

// user Msg
typedef struct UserMsg
{
    MsgType msg;
    IWindow* wnd;
    Sint32 code;        /**< User defined Msg code */
    void *data1;        /**< User defined data pointer */
    void *data2;        /**< User defined data pointer */
} UserMsg;

typedef union Msg
{
    MsgType msg;
    CommonMsg common;
    WndMsg wnd;
    KeyboardMsg key;
    TextMsg text;
    MouseMoveMsg motion;
    MouseButtonMsg button;
    MouseWheelMsg wheel;
    DropFileMsg drop;
    UserMsg user;
} Msg;

typedef enum EventType
{
    EVENT_CLICK,
    EVENT_SCROLL,
    EVENT_KEY_ENTER,
    EVENT_TEXTCHANGE,
} EventType;

EDUI_NAMESPACE_END

#endif
